package com.ncbee.base.web.base;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ncbee.base.config.mybatis.Condition;
import com.ncbee.base.config.shiro.annotation.RequiresExtPermissions;
import com.ncbee.base.model.enums.ResultCode;
import com.ncbee.base.model.vo.Result;
import com.ncbee.base.model.vo.UserInfo;
import com.ncbee.base.service.BaseDataService;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author fengzirong
 * @Date  2018/11/22 13:46
 * @Description
 *  1:常用页面的跳转
 *  2:通用的增删查改
 *  3:定义常用的web层返回结果
 *
 **/
public abstract class BaseController<T>{
    private static final Logger logger = LoggerFactory.getLogger(BaseController.class);

    protected abstract IService<T> getTargetService();
    @Autowired
    private BaseDataService baseDataService;

    @Value("${result.page.code}")
    private String code;
    @Value("${result.page.msg}")
    private String msg;
    @Value("${result.page.count}")
    private String count;
    @Value("${result.page.data}")
    private String data;

    @RequiresExtPermissions("listPage")
    @RequestMapping("/listPage")
    public String showList(HttpServletRequest request){
       beforeShowList(request);
       return getListPageUrl();
    }

    public abstract String getListPageUrl();

    protected void beforeShowList(HttpServletRequest request){}

     @RequestMapping("/addPage")
     public String showAddPage(HttpServletRequest request){
        beforeShowAdd(request);
        return getAddPageUrl();
     }

    protected abstract String getAddPageUrl();

    protected void beforeShowAdd(HttpServletRequest request){}
    @RequestMapping("/editPage")
    public String showEditPage(HttpServletRequest request,Long id){
        T entity=getTargetService().getById(id);
        beforeShowEdit(request,entity);
        if(entity!=null){
            String simpleClassName=entity.getClass().getSimpleName();
            simpleClassName = simpleClassName.replaceFirst(simpleClassName.substring(0, 1), simpleClassName.substring(0, 1).toLowerCase());
            request.setAttribute(simpleClassName, entity);
        }
        return getEditPageUrl();
    }

    protected abstract String getEditPageUrl();

    protected void beforeShowEdit(HttpServletRequest request, T entity){}


    /*
     *  单表条件查询所有
     *  结合mybatis-plus中的QueryWrapper生成单表的sql
     *  params: conditions 为json格式数据：如下
     *  通常情况下:
     *  [
     *  {columnName(必填):'列名',operator(可选默认为=):'操作符',value(可选):'查询的值',orderVal(可选):'asc|desc'},
     *  {columnName(必填):'列名',operator:'操作符',value:'查询的值',},
     *  ]
     *  特殊 :当操作符为between时，value:'xxx,yyy' 这种类型格式
     *
     */
    @ResponseBody
    @RequestMapping("getList")
    protected Object getList(String conditions,Long page,Long limit,String paging){
        long start = System.currentTimeMillis();
        QueryWrapper<T> queryWrapper=null;
        if(!StringUtils.isEmpty(conditions)){
          List<Condition> list=null;
          try{
            list=JSONArray.parseArray(conditions,Condition.class);
          }
          catch (Exception e){
              logger.error("转换condition时发生错误");
              return renderError("condition数据格式错误");
          }
          //传过来的查询条件不为空,开始组装QueryWrapper
          if(!CollectionUtils.isEmpty(list)){
              queryWrapper=new QueryWrapper<T>();
              for(Condition condition:list){
                  String operator=condition.getOperator();
                  String columnName=condition.getColumnName();
                  Object value=condition.getValue();
                  String orderVal=condition.getOrderVal();
                  //判断是需要排序，不为空则开始排序
                  switch(operator){
                      case "isNull":
                          queryWrapper.isNull(columnName);
                          break;
                      case "isNotNull":
                          queryWrapper.isNotNull(columnName);
                          break;
                      case "=":
                          queryWrapper.eq(columnName,value);
                          break;
                      case "like":
                          queryWrapper.like(columnName,value);
                          break;
                      case "between":
                         Object [] valueArray=value.toString().split(",");
                         queryWrapper.between(columnName,valueArray[0],valueArray[1]);
                          break;
                      case ">":
                          queryWrapper.gt(columnName,value);
                          break;
                      case ">=":
                          queryWrapper.ge(columnName,value);
                          break;
                      case "<":
                          queryWrapper.lt(columnName,value);
                          break;
                      case "<=":
                          queryWrapper.le(columnName,value);
                          break;
                      case "<>":
                          queryWrapper.ne(columnName,value);
                          break;
                      case "inSql":
                          queryWrapper.gt(columnName,value);
                          break;
                      case "order":
                          if(!StringUtils.isEmpty(orderVal)){
                              if("asc".equals(orderVal)){
                                  queryWrapper.orderByAsc(columnName);
                              }else if("desc".equals(orderVal)){
                                  queryWrapper.orderByAsc(columnName);
                              }
                          }
                          break;
                      default:

                  }
              }
          }
        }
        List<T> list=null;
        IPage<T> pageList=null;
        if(!StringUtils.isEmpty(paging)){
            pageList=new Page<T>();
            if(page!=null){
                pageList.setCurrent(page);
            }
            if(limit!=null){
                pageList.setSize(limit);
            }
        }
        try{
            if(StringUtils.isEmpty(paging)){//不开启分页模式
                list=getTargetService().list(queryWrapper);
            }else{//开启分页模式
                pageList=getTargetService().page(pageList,queryWrapper);
            }
        }
        catch(Exception e){
           logger.error("执行查询期间发生错误");
           renderError("查询期间发生错误");
        }
        logger.info("本次查询一共耗时"+(System.currentTimeMillis()-start)+"ms");
        if(StringUtils.isEmpty(paging)){
            return list;
        }
        return renderPage(pageList);
    }

    /*
     * @Author fengzirong
     * @Description  单表保存对象操作
     * @Date  2018/11/22 20:31
     * @Param
     * @return
     **/
    @Transactional
    @ResponseBody
    @RequestMapping("/save")
    public Object save(HttpServletRequest request,@Valid T entity){
        beforeSave(request,entity);
        boolean flag=getTargetService().save(entity);
        if(flag){
            afterSave(request,entity);
            return renderSuccess();
        }
        return renderError();
    }
    @Transactional
    @ResponseBody
    @RequestMapping("/update")
    public Object update(HttpServletRequest request,@Valid T entity){
        beforeUpdate(request,entity);
        boolean flag=getTargetService().updateById(entity);
        if(flag){
            afterUpdate(request,entity);
           return renderSuccess();
        }
        return renderError();
    }
    @Transactional
    @ResponseBody
    @RequestMapping("/delete")
    public Object delete(HttpServletRequest request,String ids){
        boolean flag;
        if(StringUtils.isEmpty(ids)){
            return renderError();
        }
        beforeDelete(request,ids);
        if(ids.startsWith("[")){
            List<Long> params= JSONArray.parseArray(ids,Long.class);
            flag=getTargetService().removeByIds(params);
        }else{
            Long id=Long.parseLong(ids);
            flag=getTargetService().removeById(id);
        }
        afterDelete(request,ids);
        if(flag){
            return renderSuccess();
        }
        return renderError();
    }



    protected Result renderSuccess(){
        Result result=Result.getInstance(ResultCode.SUCCESS);
        return result;
    }
    protected Result renderSuccess(String msg){
        Result result=Result.getInstance(ResultCode.SUCCESS);
        result.setMsg(msg);
        return result;
    }
    protected Result renderSuccess(int i){
        Result result=Result.getInstance(ResultCode.SUCCESS);
        result.setMsg("成功处理"+i+"条记录");
        return result;
    }
    protected Result renderError(){
        Result result=Result.getInstance(ResultCode.BASE_ERROR);
        return result;
    }
    protected Result renderError(String msg){
        Result result=Result.getInstance(ResultCode.BASE_ERROR);
        result.setMsg(msg);
        return result;
    }

    /**
     * 采用layui 默认表格基本格式
     * {
     *   "code": 0,
     *   "msg": "",
     *   "count": 1000,
     *   "data": [{}, {}]
     * }
     * 抽取到配置文件
     * @param page
     * @return
     */
    protected Object renderPage(IPage<?> page){
        Map<String,Object> map=new HashMap<String,Object>(4);
        String tip="处理成功";
        if(CollectionUtils.isEmpty(page.getRecords())){
            tip="暂无记录";
        }
        map.put(data,page.getRecords());
        map.put(count,page.getTotal());
        map.put(msg,tip);
        map.put(code,0);
        return map;
    }
    protected void beforeDelete(HttpServletRequest request, String ids) {
    }
    protected void beforeUpdate(HttpServletRequest request, T entity){
    }
    protected void afterUpdate(HttpServletRequest request, T entity){
    }
    protected void beforeSave(HttpServletRequest request, T entity){
    }
    protected void afterSave(HttpServletRequest request, T entity){
    }
    protected void afterDelete(HttpServletRequest request, String ids) {
    }
    /**
     * 获取当前登录用户ID
     * @return
     */
    protected Long getCurrentUserId(){
      UserInfo userInfo=(UserInfo)SecurityUtils.getSubject().getPrincipal();
      return userInfo.getId();
    }
}
